package com.yanqu.xiuxian.crosssystem.manger.elementalbonds.logic;

import com.yanqu.xiuxian.config.elementalbonds.ElementalBondsConfigMgr;
import com.yanqu.xiuxian.config.elementalbonds.ElementalBondsHardLevelConfig;
import com.yanqu.xiuxian.config.elementalbonds.ElementalBondsModeConfig;
import com.yanqu.xiuxian.config.elementalbonds.enums.ElementalBondsBlockType;
import com.yanqu.xiuxian.config.elementalbonds.enums.ElementalBondsColorType;
import com.yanqu.xiuxian.config.elementalbonds.enums.ElementalBondsDirectionType;
import com.yanqu.xiuxian.config.elementalbonds.enums.ElementalBondsEffectType;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.data.ElementalBondsGameData;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.data.ElementalBondsPlayerData;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.data.ElementalBondsRoomData;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.ElementalBondsBlock;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.ElementalBondsBlockEffect;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.ElementalBondsOperateEffect;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.enums.*;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.param.ElementalBondsAiMoveParam;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.param.ElementalBondsCardParam;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.param.ElementalBondsMoveParam;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.param.ElementalBondsSkillParam;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.result.ElementalBondsOperateResult;
import com.yanqu.xiuxian.utils.RandomHelper;

import java.util.*;

public class ElementalBondsGameLogic {

    public static ElementalBondsOperateResult operateMove(ElementalBondsRoomData elementalBondsRoomData, boolean isPlayer1,
                                                          ElementalBondsMoveParam elementalBondsMoveParam, int guideDropNo, int roomRound) {
        return ElementalBondsMoveLogic.operate(elementalBondsRoomData, isPlayer1, elementalBondsMoveParam, guideDropNo, roomRound);
    }

    public static ElementalBondsOperateResult operateUseSkill(ElementalBondsRoomData elementalBondsRoomData, boolean isPlayer1,
                                                              ElementalBondsSkillParam elementalBondsSkillParam, int guideDropNo, int roomRound) {
        return ElementalBondsSkillLogic.operate(elementalBondsRoomData, isPlayer1, elementalBondsSkillParam, guideDropNo, roomRound);
    }

    public static ElementalBondsOperateResult operateUseCard(ElementalBondsRoomData elementalBondsRoomData, boolean isPlayer1,
                                                             ElementalBondsCardParam elementalBondsCardParam, int guideDropNo, int roomRound) {
        return ElementalBondsCardLogic.operate(elementalBondsRoomData, isPlayer1, elementalBondsCardParam, guideDropNo, roomRound);
    }

    public static List<List<ElementalBondsBlock>> getInitBlockList( Random random) {
        int width = ElementalBondsConfigMgr.getInstance().getBlockListWidth();
        int height = ElementalBondsConfigMgr.getInstance().getBlockListHeight();
        int colorCount = ElementalBondsConfigMgr.getInstance().getColorNum();
        int limitCount = height * width / colorCount;

        int tryTimes = 30; // 大于10
        int tryBestTimes = 15; // 比tryTimes小，大于等于0

        for (int i = 0; i < tryTimes; i++) {

            // 各颜色数量
            Map<Integer, Integer> colorCountMap = new HashMap<>();

            List<List<ElementalBondsBlock>> blockList = new ArrayList<>();
            for (int y = 0; y < height; y++) {
                blockList.add(new ArrayList<>());
                for (int x = 0; x < width; x++) {
                    List<Integer> colorList = ElementalBondsBlockLogic.getCanCreateColor(blockList, colorCount, x, y);

                    int chooseColor;
                    // 所有颜色都不能选，这里说明代码或配置有问题
                    if (colorList.isEmpty()) {
                        chooseColor = ElementalBondsColorType.GOLDEN.getType();
                    } else {
                        // 颜色使用数少的权重高
                        List<Integer> weightList = new ArrayList<>();
                        int avgCount = colorList.stream().mapToInt(color -> colorCountMap.getOrDefault(color, 0)).sum() / colorList.size();
                        for (int color : colorList) {
                            int tmpCount = colorCountMap.getOrDefault(color, 0);
                            weightList.add(tmpCount > avgCount || tmpCount >= limitCount ? 250 : 1000);
                        }
                        // 如果可选颜色都没权重了，则全部相同权重随机
                        if (weightList.stream().noneMatch(weight -> weight > 0)) {
                            Collections.fill(weightList, 1);
                        }
                        chooseColor = colorList.get(RandomHelper.getRandomIndexByWeight(weightList, random));
                    }

                    blockList.get(y).add(new ElementalBondsBlock(x, y, chooseColor));
                    colorCountMap.put(chooseColor, colorCountMap.getOrDefault(chooseColor, 0) + 1);
                }
            }

            ElementalBondsGameData elementalBondsGameData = ElementalBondsGameData.createElementalBondsGameData(ElementalBondsSceneType.EMPTY.getType(), blockList);
            ElementalBondsHardLevelConfig checkInitBoardConfig = ElementalBondsConfigMgr.getInstance().getCheckHardLevelConfig();
            ElementalBondsAiMoveParam elementalBondsAiMoveParam = ElementalBondsAiLogic.getBestAiMove(elementalBondsGameData, 1, null, checkInitBoardConfig);
            if (elementalBondsAiMoveParam != null) {
                int moveWeight = elementalBondsAiMoveParam.getWeight(checkInitBoardConfig);
                if (i < tryBestTimes && moveWeight < checkInitBoardConfig.getMoveWeightList().get(0)) {
                    return blockList;
                }
                if (i >= tryBestTimes) {
                    return blockList;
                }
            }

        }

        // 说明代码有问题
        throw new RuntimeException("ElementalBondsGameLogic getInitBlockList error!");
    }

    public static void turnChangeResetBlock(List<List<ElementalBondsBlock>> blockList, ElementalBondsOperateResult elementalBondsOperateResult) {
        Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
        for (int y = 0; y < blockList.size(); y++) {
            for (int x = 0; x < blockList.get(y).size(); x++) {
                ElementalBondsBlock elementalBondsBlock = blockList.get(y).get(x);

                List<ElementalBondsBlockEffect> elementalBondsBlockEffectList = elementalBondsBlock.getElementalBondsBlockEffectList();
                for (int i = 0; i < elementalBondsBlockEffectList.size(); i++) {
                    if (elementalBondsBlockEffectList.get(i).getEffectType().isTurnReset()) {
                        elementalBondsBlockEffectList.remove(i--);
                        elementalBondsBlockSet.add(elementalBondsBlock);
                    }
                }
                if (elementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.ROCKET) {
                    elementalBondsBlock.setElementalBondsBlockType(ElementalBondsBlockType.NORMAL);
                    elementalBondsBlock.setElementalBondsDirectionType(ElementalBondsDirectionType.UP);
                    blockList.get(y).set(x, elementalBondsBlock);
                    elementalBondsBlockSet.add(elementalBondsBlock);
                }
                if (elementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.PAPER_FLOWER) {
                    elementalBondsBlock.setElementalBondsBlockType(ElementalBondsBlockType.NORMAL);
                    blockList.get(y).set(x, elementalBondsBlock);
                    elementalBondsBlockSet.add(elementalBondsBlock);
                }
                if (elementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.METEOR_BOMB) {
                    elementalBondsBlock.setElementalBondsBlockType(ElementalBondsBlockType.NORMAL);
                    blockList.get(y).set(x, elementalBondsBlock);
                    elementalBondsBlockSet.add(elementalBondsBlock);
                }
                if (elementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.SMART_BOX) {
                    // 手工少女-机巧盒 回合结束后替换
                    elementalBondsBlock.setElementalBondsBlockType(ElementalBondsBlockType.NORMAL);
                    blockList.get(y).set(x, elementalBondsBlock);
                    // 随机稳定盘面的颜色
                    Set<Integer> colorSet = new HashSet<>();
                    // 获取上下左右的颜色
                    int[][] dirs = new int[][]{{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
                    for (int[] dir : dirs) {
                        if (ElementalBondsBlockLogic.exist(blockList, x + dir[0], y + dir[1])) {
                            ElementalBondsBlock targetElementalBondsBlock = blockList.get(y + dir[1]).get(x + dir[0]);
                            colorSet.add(targetElementalBondsBlock.getColor());
                        }
                    }
                    List<Integer> chooseColorList = new ArrayList<>();
                    for (ElementalBondsColorType elementalBondsColorType : ElementalBondsColorType.values()) {
                        if (elementalBondsColorType == ElementalBondsColorType.NONE) {
                            continue;
                        }
                        if (colorSet.contains(elementalBondsColorType.getType())) {
                            continue;
                        }
                        chooseColorList.add(elementalBondsColorType.getType());
                    }
                    Random random = new Random();
                    Collections.shuffle(chooseColorList, random);
                    elementalBondsBlock.setColor(chooseColorList.get(0));
                    elementalBondsBlockSet.add(elementalBondsBlock);
                }
                if (elementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.SMART_BOX_LANDMINE) {
                    elementalBondsBlock.setElementalBondsBlockType(ElementalBondsBlockType.NORMAL);
                    blockList.get(y).set(x, elementalBondsBlock);
                    elementalBondsBlockSet.add(elementalBondsBlock);
                }
            }
        }

        // 有变化要添加表现
        if (!elementalBondsBlockSet.isEmpty()) {
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(ElementalBondsEffectType.UPDATE_BLOCK, new ArrayList<>(elementalBondsBlockSet)));
        }
    }

    public static boolean isStepMax(int modeId, ElementalBondsPlayerData elementalBondsPlayerData) {
        ElementalBondsModeConfig elementalBondsModeConfig = ElementalBondsConfigMgr.getInstance().getModeConfigMap().get(modeId);
        return elementalBondsPlayerData.getStep() >= elementalBondsModeConfig.getMaxStep();
    }

}
